#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "xcommon.h"

#include "lifo.h"

#include "llist.h"
#include "xmalloc.h"	// for xcalloc and xfree
#include "xstring.h"	// for xstrdup

inline LIFO *lf_new() {
// Returns a new list
	return (LIFO *)xcalloc(1, sizeof(LIFO));
}

bool lf_is_valid(LIFO *sl) {
	if(!sl) return false;
	if(((!sl->start || !sl->end) && sl->numel) || (sl->start && sl->start==sl->end && sl->numel!=1)) return false;
	if((sl->start && sl->start->prev) || (sl->end && sl->end->next)) return false;

	return true;
}

void lf_push(LIFO *sl, void *data) {
	if(!lf_is_valid(sl)) return;

	sl->end=ll_append_el(&sl->end, data);
	if(!sl->start) sl->start=sl->end;
	sl->numel++;
}

inline u32 lf_get_num_el(LIFO *sl) {
// Returns the number of elements in the stack list
	return lf_is_valid(sl)?sl->numel:0;
}

void *lf_pop(LIFO *sl) {
	if(!lf_is_valid(sl) || !sl->numel) return NULL;

    void *ret=sl->end->data;
    LLIST *tmp=sl->end;
	sl->end=sl->end->prev;
	sl->numel--;
	if(!sl->end) sl->start=NULL;

	ll_free_el(tmp);

	return ret;
}

void lf_free(LIFO *sl) {
	if(!lf_is_valid(sl)) return;

	ll_free_all(sl->start);

	bzero(sl, sizeof(LIFO));

	xfree(sl);
}

void lf_free_handler(LIFO *sl, datahandler lfh) {
	if(!lf_is_valid(sl)) return;

	ll_free_all_handler(sl->start, lfh);

	bzero(sl, sizeof(LIFO));

	xfree(sl);
}

